package control;

import control.bean.ControlBeanConstant;
import control.bean.ControlPropertiesBean;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * User: Deshun
 * Date: 2/20/13
 * Time: 11:09 AM
 * To change this template use File | Settings | File Templates.
 */
public class Listbox extends Control {

    private JScrollPane scrollPane;
    private java.util.List<String> optionList;
    private JList<String> list;
    private JTextField editTextField;
    private JPopupMenu editPopup;
    private Class<?> modelClass;
    DefaultListModel listModel;

    public Listbox() {
        fieldType = ControlBeanConstant.LISTBOX;
        listModel = new DefaultListModel<String>();
        optionList = new ArrayList<String>();

        scrollPane = new JScrollPane();
        list = new JList<String>();
        this.modelClass = DefaultListModel.class;

        optionList.add("Double Click to Edit");
        optionList.add("Double Click to Edit");
        optionList.add("Double Click to Edit");
        optionList.add("Double Click to Edit");

        buildControlPanel();
        buildPropertiesPanel();
    }
    @Override
    public Component buildControlPanel() {
        if ( controlPanel != null && controlPanel.getComponentCount() > 0 ) {
            controlPanel.removeAll();
        } else {
            controlPanel = new JPanel(new GridBagLayout());
        }
        label = new JTextField(super.labelText);

        GridBagConstraints constraints = new GridBagConstraints();

        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.ipadx = 130;
        constraints.insets = new Insets(5, 5, 0, 5);
        constraints.anchor = GridBagConstraints.NORTHWEST;
        constraints.fill = GridBagConstraints.HORIZONTAL;

        controlPanel.add(label, constraints);

        listModel.clear();
        //fill up list again

        for ( String current : optionList) {
            listModel.addElement(current);
        }

        list.removeAll();
        list.setModel(listModel);

        constraints.gridx = 1;
        constraints.gridy = 0;
        constraints.ipady = 50;
        constraints.insets = new Insets(5,0,0,5);
        constraints.anchor = GridBagConstraints.NORTHWEST;
        constraints.fill = GridBagConstraints.HORIZONTAL;

        scrollPane.setViewportView(list);

        controlPanel.add(scrollPane, constraints);

        controlPanel.addFocusListener(new ControlFocusAdaptor());
        controlPanel.addMouseListener(new ControlMouseAdaptor());

        label.addFocusListener(new ControlFocusAdaptor());
        label.addMouseListener(new ControlMouseAdaptor());

        list.addFocusListener(new ControlFocusAdaptor());
        list.addMouseListener(new ControlMouseAdaptor());
        list.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    ActionEvent event = new ActionEvent(list, ActionEvent.ACTION_PERFORMED, "");
                    actionPerformed(event);
                }
            }
        });

        return controlPanel;
    }

    @Override
    public Component buildPropertiesPanel() {
        propertiesPanel = new JPanel(new GridBagLayout());

        fieldProperties = new JLabel("Field Properties");

        controlLabel    = new JLabel("Control Name");
        controlName     = new JTextField();

        hint            = new JCheckBox("Hint");
        required        = new JCheckBox("Required");
        readOnly        = new JCheckBox("Read Only");

        GridBagConstraints constraints = new GridBagConstraints();
        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.gridwidth = 1;
//        constraints.ipadx = 130;
        constraints.ipady = 14;
        constraints.anchor = GridBagConstraints.NORTHWEST;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.insets = new Insets(10, 0, 0, 0);
        propertiesPanel.add(fieldProperties, constraints);

        constraints = new GridBagConstraints();
        constraints.gridx = 0;
        constraints.gridy = 1;
        constraints.ipadx = 0;
        constraints.anchor = GridBagConstraints.NORTHWEST;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.insets = new Insets(10, 0, 0, 0);
        propertiesPanel.add(controlLabel, constraints);

        constraints = new GridBagConstraints();
        constraints.gridx = 0;
        constraints.gridy = 2;
        constraints.gridwidth = 1;
        //constraints.gridheight = 2;
//        constraints.ipadx = 114;
        constraints.anchor = GridBagConstraints.NORTHWEST;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.insets = new Insets(5, 0, 0, 0);
        propertiesPanel.add(controlName, constraints);

        constraints = new GridBagConstraints();
        constraints.gridx = 0;
        constraints.gridy = 3;
        constraints.gridwidth = 1;
        constraints.anchor = GridBagConstraints.NORTHWEST;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.insets = new Insets(10, 0, 0, 0);
        propertiesPanel.add(hint, constraints);

        constraints = new GridBagConstraints();
        constraints.gridx = 0;
        constraints.gridy = 4;
        constraints.gridwidth = 1;
        constraints.anchor = GridBagConstraints.NORTHWEST;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.insets = new Insets(1, 0, 0, 0);
        propertiesPanel.add(required, constraints);

        constraints = new GridBagConstraints();
        constraints.gridx = 0;
        constraints.gridy = 5;
        constraints.gridwidth = 1;
        constraints.anchor = GridBagConstraints.NORTHWEST;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.insets = new Insets(1, 0, 0, 0);
        propertiesPanel.add(readOnly, constraints);

        Component strut = Box.createHorizontalStrut(160);
        constraints.gridy = 6;
        propertiesPanel.add(strut, constraints);

        return propertiesPanel;
    }

    protected void applyValueToModel(String value, ListModel model, int row) {
        DefaultListModel dlm = (DefaultListModel) model;
        dlm.set(row, value);
        optionList.set(row, value);
    }

    public void actionPerformed(ActionEvent e) {
        list = (JList) e.getSource();
        ListModel model = list.getModel();

        if (!modelClass.isAssignableFrom(model.getClass())) return;

        //  Do a lazy creation of the popup editor

        if (editPopup == null)
            createEditPopup();

        //  Position the popup editor over top of the selected row

        int row = list.getSelectedIndex();
        Rectangle r = list.getCellBounds(row, row);

        editPopup.setPreferredSize(new Dimension(r.width, r.height));
        editPopup.show(list, r.x, r.y);

        //  Prepare the text field for editing

        editTextField.setText(list.getSelectedValue().toString());
        editTextField.selectAll();
        editTextField.requestFocusInWindow();
    }

    /*
     *  Create the popup editor
     */
    private void createEditPopup() {
        //  Use a text field as the editor

        editTextField = new JTextField();
        Border border = UIManager.getBorder("List.focusCellHighlightBorder");
        editTextField.setBorder(border);

        //  Add an Action to the text field to save the new value to the model
        editTextField.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String value = editTextField.getText();
                ListModel model = list.getModel();
                int row = list.getSelectedIndex();
                applyValueToModel(value, model, row);
                editPopup.setVisible(false);
            }
        });

        editTextField.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                String value = editTextField.getText();
                ListModel model = list.getModel();
                int row = list.getSelectedIndex();
                applyValueToModel(value, model, row);
                editPopup.setVisible(false);
            }
        });

        //  Add the editor to the popup

        editPopup = new JPopupMenu();
        editPopup.setBorder(new EmptyBorder(0, 0, 0, 0));
        editPopup.add(editTextField);
    }
    //TODO add options

    private String concat() {
        String concatOptions = new String();

        for ( String current : optionList ) {
            concatOptions += current+",";
        }

        //trim the last comma away and return
        return concatOptions.substring(0, concatOptions.length()-1);
    }

    public String[] breakdown(String options) {
        return options.split(",");
    }

    public void buildOptionsFromString(String[] input) {
        if ( optionList == null ) {
            optionList = new ArrayList<String>();
        } else {
            optionList.clear();
        }

        //this method doesn't allow me to add new options to the list anymore
        //optionList = Arrays.asList(input);

        for ( String current : input ) {
            optionList.add(current);
        }
        optionList.add("Double Click to Edit");
        buildControlPanel();
    }

    public ControlPropertiesBean exportData() {
        super.exportData();

        try {
            controlPropertiesBean.addProperty(ControlBeanConstant.OPTIONS, concat());
        } catch ( Exception e ) {
            System.out.println("Drop down list not set.");
        }
        return controlPropertiesBean;
    }

    public void importData(ControlPropertiesBean controlPropertiesBean) {
        try {
            super.importData(controlPropertiesBean);
            buildOptionsFromString(breakdown(controlPropertiesBean.getProperty(ControlBeanConstant.OPTIONS)));
        } catch ( Exception e ) {
            System.out.println("failed to load at listbox");
        }
    }
}
